package com.info33.platform.system.dic.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.info33.platform.common.constant.TableConstant;
import com.info33.platform.common.exception.ResultException;
import com.info33.platform.common.mvc.vo.Result;
import com.info33.platform.common.util.SysUtil;
import com.info33.platform.system.dic.dao.SysDicDao;
import com.info33.platform.system.dic.dto.SysDicDTO;
import com.info33.platform.system.dic.entity.SysDic;
import com.info33.platform.system.dic.service.SysDicService;
import com.info33.platform.system.dic.vo.SysDicVO;
import com.info33.platform.system.vo.SysUserVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 系统 - 字典 v2
 *
 * @author nyj2one
 * @since 2022-11-23 11:08:39
 */
@Service
@RequiredArgsConstructor
public class SysDicServiceImpl extends ServiceImpl<SysDicDao, SysDic> implements SysDicService {

    private final SysDicDao sysDicDao;

    /**
     * 根据数据源生成树型结构
     *
     * @param id   父 id
     * @param list 数据源
     * @return 树型结构
     */
    private List<SysDicVO> generateTreeList(Long id, List<SysDicVO> list) {
        List<SysDicVO> collect = list
                .stream()
                .filter(l -> l.getPid().equals(id))
                .collect(Collectors.toList());
        collect
                .stream()
                .parallel()
                .forEach(l -> l.setChildren(generateTreeList(l.getId(), list)));
        return ObjectUtils.isEmpty(collect) ? null : collect;
    }

    @Override
    public IPage<SysDicVO> pcPage(Page<SysDic> page, SysDicDTO dto) {
        dto.setTenantId(SysUtil.getTenantId());
        return sysDicDao.pcPage(page, dto);
    }

    @Override
    public Result<Object> pcAdd(SysDicDTO dto) {
        SysUserVO currentUser = SysUtil.getCurrentUser();
        // 公共字典
        if (Boolean.TRUE.equals(dto.getCommon())) {
            if (Boolean.TRUE.equals(SysUtil.isSysTenantAdmin(currentUser))) {
                dto.setCommon(Boolean.TRUE);
            } else {
                throw new ResultException("无法新增公共内容！权限不足");
            }
        }
        // 赋值序列码
        SysDic bro = this.getOne(
                new LambdaQueryWrapper<SysDic>()
                        .eq(SysDic::getPid, dto.getPid())
                        .eq(SysDic::getModIndex, dto.getModIndex())
                        .orderByDesc(SysDic::getTreeCode)
                        .last(TableConstant.LIMIT_ONE));
        if (ObjectUtils.isEmpty(bro)) {
            SysDic par = this.getById(dto.getPid());
            if (ObjectUtils.isEmpty(par)
                    && 0L != dto.getPid()) {
                throw new ResultException("数据异常！请稍后重试");
            }
            dto.setTreeCode(ObjectUtils.isEmpty(par)
                    ? dto.getModIndex()
                    : par.getTreeCode());
            dto.setTreeCode(dto.getTreeCode() + 100);
        } else {
            int i = Integer.parseInt(
                    bro.getTreeCode().substring(bro.getTreeCode().length() - 3),
                    16);
            if (i > 0Xff9) {
                // 预留几个空间，防止异常情况
                return Result.error("该项字典已达到上限！不可以继续新增");
            }
            dto.setTreeCode(
                    bro.getTreeCode().substring(0, bro.getTreeCode().length() - 3)
                            + Integer.toString(++i, 16));
        }
        return Boolean.TRUE.equals(this.save(dto))
                ? Result.ok(dto)
                : Result.error("新增失败！请稍后重试");
    }

    @Override
    public Result<Object> pcEdit(SysDicDTO dto) {
        SysUserVO currentUser = SysUtil.getCurrentUser();
        SysDic old = this.getById(dto.getId());
        // 检查公共字典权限
        if (Boolean.FALSE.equals(SysUtil.isSysTenantAdmin(currentUser))
                && old.getCommon().equals(Boolean.TRUE)) {
            return Result.error("此字典无法修改！权限不足");
        }
        return Boolean.TRUE.equals(this.updateById(dto))
                ? Result.ok()
                : Result.error("修改失败！请稍后重试");
    }

    @Override
    public Result<Object> pcRemove(Long id) {
        SysUserVO currentUser = SysUtil.getCurrentUser();
        SysDic old = this.getById(id);
        if (old.getCommon().equals(Boolean.TRUE)
                && Boolean.FALSE.equals(SysUtil.isSysTenantAdmin(currentUser))) {
            return Result.error("此字典无法删除！权限不足");
        }
        SysDic son = this.getOne(
                new LambdaQueryWrapper<SysDic>()
                        .eq(SysDic::getPid, id)
                        .and(l ->
                                l.eq(SysDic::getTenantId, currentUser.getTenant().getId())
                                        .or()
                                        .eq(SysDic::getCommon, true))
                        .last(TableConstant.LIMIT_ONE));
        if (!ObjectUtils.isEmpty(son)) {
            return Result.error("此字典存在子字典，请先删除子字典");
        }
        return Boolean.TRUE.equals(this.removeById(id))
                ? Result.ok()
                : Result.error("删除失败！请稍后重试");
    }

    @Override
    public List<SysDicVO> pcTree(String modIndex) {
        return generateTreeList(0L, sysDicDao.pcTree(modIndex, SysUtil.getTenantId()));
    }

    @Override
    public List<SysDicVO> pcList(String modIndex) {
        return sysDicDao.pcList(modIndex, SysUtil.getTenantId());
    }

    @Override
    public List<List<SysDicVO>> pcListByMods(String... modIndexes) {
        List<List<SysDicVO>> list = new ArrayList<>();
        List<SysDicVO> datas = sysDicDao.pcListByMods(StringUtils.arrayToCommaDelimitedString(modIndexes));
        for (String index : modIndexes) {
            list.add(datas.stream().filter(l -> l.getModIndex().equals(index)).collect(Collectors.toList()));
        }
        return list;
    }

    @Override
    public List<SysDicVO> openList(SysDicDTO dto) {
        return sysDicDao.openList(dto);
    }

    @Override
    public List<SysDicVO> openTree(SysDicDTO dto) {
        return generateTreeList(dto.getPid(), sysDicDao.openTree(dto));
    }

    @Override
    public List<List<SysDicVO>> openListByMods(
            SysDicDTO dto,
            String... modIndexes) {
        List<List<SysDicVO>> list = new ArrayList<>();
        List<SysDicVO> datas = sysDicDao.openListByMods(
                dto,
                StringUtils.arrayToCommaDelimitedString(modIndexes));
        for (String index : modIndexes) {
            list.add(datas.stream().filter(l -> l.getModIndex().equals(index)).collect(Collectors.toList()));
        }
        return list;
    }

}
